/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stdio.h>
#include <stdint.h>

#include "aos/hal/gpio.h"
#include "aos/hal/uart.h"
#include "aos/hal/i2c.h"
#include "aos/kernel.h"

#include "k_config.h"
#include "k_api.h"
#include "board.h"
#include "pin_mux.h"

#ifdef WITH_LWIP
#include "lwip/opt.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "lwip/inet.h"

#include "ethernetif.h"
#endif
#include "hal_uart.h"
#include "soc_init.h"

#if defined (__CC_ARM) && defined(__MICROLIB)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#elif defined(__ICCARM__)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#else
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#endif /* defined (__CC_ARM) && defined(__MICROLIB) */

uart_mapping_s st_uart_mapping_table[PORT_UART_SIZE] =
{
    {PORT_UART_STD,   LPUART1, 512},
    {PORT_UART_485_1, LPUART2, 2048},
    {PORT_UART_485_2, LPUART1, 2048},
    {PORT_UART_485_3, LPUART3, 2048},
    {PORT_UART_422_1, LPUART6, 2048},
    {PORT_UART_4G,    LPUART4, 8192}
};

/* Global Variable for VFS DEBUG Output */
uart_dev_t uart_0 = {
    .port = PORT_UART_STD,                                                              /* uart port */
    .config = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED}, /* uart config */
    .priv = NULL                                                                        /* priv data */
};

uart_dev_t uart_485_1 = {
    .port = PORT_UART_485_1,                                                            /* uart port */
    .config = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED}, /* uart config */
    .priv = NULL                                                                        /* priv data */
};

/*can not be used at the same time with debug uart port*/
uart_dev_t uart_485_2 = {
    .port = PORT_UART_485_1,                                                            /* uart port */
    .config = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED}, /* uart config */
    .priv = NULL                                                                        /* priv data */
};

uart_dev_t uart_485_3 = {
    .port = PORT_UART_485_3,                                                            /* uart port */
    .config = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED}, /* uart config */
    .priv = NULL                                                                        /* priv data */
};

uart_dev_t uart_422_1 = {
    .port = PORT_UART_422_1,                                                            /* uart port */
    .config = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED}, /* uart config */
    .priv = NULL                                                                        /* priv data */
};

uart_dev_t uart_4G = {
    .port = PORT_UART_4G,                                                               /* uart port */
    .config = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED}, /* uart config */
    .priv = NULL                                                                        /* priv data */
};


#ifdef WITH_LWIP
extern struct netif fsl_netif0[];
#endif
extern void tcp_init(void);
extern void udp_init(void);

int lwip_tcpip_init(void);

static void stduart_init(void)
{
    hal_uart_init(&uart_0);
}

static void n720_lte_power_on()
{
    int32_t ret = 0;
    gpio_dev_t st_4g_en = {0};

    st_4g_en.port = PORT_GPIO_4G_EN;
    st_4g_en.config = OUTPUT_PUSH_PULL;
    st_4g_en.priv = NULL;

    ret = hal_gpio_init(&st_4g_en);
    if (ret) {
        printf("GPIO 4G_EN init fail %d \r\n", ret);
        return;
    }

    ret = hal_gpio_output_high(&st_4g_en);
    if (ret) {
        printf("GPIO 4G_EN output high fail %d \r\n", ret);
        return;
    }
    
    
    return;
}

void board_peripheral_init(void)
{
    /*default uart init*/
    stduart_init();
    /*default codec I2c init*/
    codec_i2c_init();
    /*power on 4g n720*/
    n720_lte_power_on();
}

void platform_init(void)
{
    BOARD_InitPins();
    BOARD_InitI2C1Pins();
    BOARD_InitSaiPins();
    BOARD_BootClockRUN();
    BOARD_USDHCClockConfiguration();
}

#ifdef WITH_LWIP
static void tcpip_init_done(void *arg)
{
    long long ts = aos_now();
    srand((unsigned int)ts);
    tcp_init();
    udp_init();

#if LWIP_IPV4
    ip4_addr_t ipaddr, netmask, gw;
    memset(&ipaddr, 0, sizeof(ipaddr));
    memset(&netmask, 0, sizeof(netmask));
    memset(&gw, 0, sizeof(gw));
    ip4addr_aton("192.168.1.220", &ipaddr);
    ip4addr_aton("255.255.255.0", &netmask);
    //gw = inet_addr("192.168.1.220");
    netif_add(&fsl_netif0[0], &ipaddr, &netmask, &gw, NULL, ethernetif0_init, tcpip_input);
#endif

#if LWIP_IPV6
#if !LWIP_IPV4
    netif_add(&fsl_netif0[0], NULL, ethernetif0_init, tcpip_input);
#endif
    netif_create_ip6_linklocal_address(&fsl_netif0[0], 1);
    fsl_netif0[0].ip6_autoconfig_enabled = 1;
#endif

    netif_set_default(&fsl_netif0[0]);
    netif_set_up(&fsl_netif0[0]);
    //tcpip_dhcpc_start(&fsl_netif0[0]);
    printf("TCP/IP initialized.");
}

int lwip_tcpip_init(void)
{
    tcpip_init(tcpip_init_done, NULL);

    return 0;
}
#endif

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
    krhino_intrpt_enter();
    krhino_tick_proc();
    krhino_intrpt_exit();
}

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  if (ch == '\n') {
    //hal_uart_send(&console_uart, (void *)"\r", 1, 30000);
    hal_uart_send(&uart_0, (void *)"\r", 1, 30000);
  }
  hal_uart_send(&uart_0, &ch, 1, 30000);
  return ch;
}

/**
  * @brief  Retargets the C library scanf function to the USART.
  * @param  None
  * @retval None
  */
GETCHAR_PROTOTYPE
{
  /* Place your implementation of fgetc here */
  /* e.g. readwrite a character to the USART2 and Loop until the end of transmission */
  uint8_t ch = EOF;
  int32_t ret = -1;

  uint32_t recv_size;
  ret = hal_uart_recv_II(&uart_0, &ch, 1, &recv_size, HAL_WAIT_FOREVER);

  if (ret == 0) {
      return ch;
  } else {
      return -1;
  }
}


